# coding=utf-8
import json
import sys
import time
from pactverify.matchers import Matcher, Like, EachLike, Term, Enum, PactVerify
import allure
import jsonpath
import pytest

from common.utils import Utils
from common.assert_operator import *
from common.db import *
from common.read_yaml import *
from common.verification import Verification

string_assert = string_assert() # 字符串校验类
pact = Pact() # 契约校验类
execute_sql = sql() # sql集合
utils = Utils()
verification = Verification()
# data = ReadYaml_By_Root_Dict("case/03_roll_back_test/03_4_RollBack_EditCondition.yml").get_yaml_data()  # 读取数据
data = ReadYaml().get_yaml_data(f'{os.path.abspath(__file__).split("_test.py")[0]}.yml')   # 读取数据

@allure.feature('修改分支条件后驳回再审批')  # 测试报告显示测试功能
class Test_03_4_RollBack_EditCondition():

    # 获取yml文件中[驳回后重新审批_确认路径]的数据参数
    approve_process_params = data['驳回后重新审批_确认路径']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(approve_process_params,"$[*][0]")
    @pytest.mark.parametrize("title, param, expect", approve_process_params,ids=ids_list)
    def test_RollBack_EditCondition_ConfirmPath(self, user_login, title, param, expect):
        Logger.info("*************** {}开始执行用例 ***************".format(title))
        allure.dynamic.description(f"{param['description']}")  # 动态解析用例描述在测试报告中展示
        user,process_name = param['user'],param['process_name']
        DBNodeVerify, MessageVerify = '数据库校验', '消息校验'
        contract_format = pact.roll_back_pact_format()
        main = user_login.goto_Approve_Process(user)    # 登录到审批类实例
        process_instance_resp = main.open_process_instance(process_name)   # 通过流程名称打开流程实例
        back_response = main.approve_submit(param,process_instance_resp)    # 驳回审批
        # 审批后校验
        verification.after_approve(process_name, back_response, expect, contract_format, DBNodeVerify,
                                   MessageVerify)
        Logger.info("*************** 【{}】重新发起 ***************".format(process_name))
        param.update(action=param['action2'])
        DBNodeVerify, MessageVerify,ConfirmPath = '重新发起数据库校验', '重新发起消息校验','确认路径校验'
        contract_format = pact.approve_pact_format()
        todo_sql = execute_sql.query_node_sql_by(process_name=process_name,all_node=False)
        reinit_user = utils.get_column_value_by_two_array(sqlserver_query_return_contain_field(todo_sql),'用户code')[0]  # 查询当前流程在办节点的用户
        reinit = user_login.goto_Approve_Process(reinit_user)
        process_instance_resp = reinit.open_process_instance(process_name)
        confirm_path_resp = reinit.approve_confirm_path(param, process_instance_resp)
        reinit_resp = reinit.approve_submit(param,process_instance_resp)
        # 审批后校验
        verification.after_approve(process_name, reinit_resp, expect, contract_format, DBNodeVerify,
                                   MessageVerify,confirm_path_resp=confirm_path_resp,confirm_path_verify=ConfirmPath)
        Logger.info("*************** {}结束执行用例 ***************".format(title))

    # 获取yml文件中[驳回后重新审批_不确认路径]的数据参数
    approve_process_params = data['驳回后重新审批_不确认路径']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(approve_process_params,"$[*][0]")
    @pytest.mark.parametrize("title, param, expect", approve_process_params,ids=ids_list)
    def test_RollBack_EditCondition_NoConfirmPath(self, user_login, title, param, expect):
        Logger.info("*************** {}开始执行用例 ***************".format(title))
        allure.dynamic.description(f"{param['description']}")  # 动态解析用例描述在测试报告中展示
        user,process_name = param['user'],param['process_name']
        DBNodeVerify, MessageVerify = '数据库校验', '消息校验'
        contract_format = pact.roll_back_pact_format()
        main = user_login.goto_Approve_Process(user)    # 登录到审批类实例
        process_instance_resp = main.open_process_instance(process_name)   # 通过流程名称打开流程实例
        back_response = main.approve_submit(param,process_instance_resp)    # 驳回审批
        # 审批后校验
        verification.after_approve(process_name, back_response, expect, contract_format, DBNodeVerify,
                                   MessageVerify)
        Logger.info("*************** 【{}】重新发起 ***************".format(process_name))
        param.update(action=param['action2'])
        DBNodeVerify, MessageVerify = '重新发起数据库校验', '重新发起消息校验'
        contract_format = pact.approve_pact_format()
        todo_sql = execute_sql.query_node_sql_by(process_name=process_name,all_node=False)
        reinit_user = utils.get_column_value_by_two_array(sqlserver_query_return_contain_field(todo_sql),'用户code')[0]  # 查询当前流程在办节点的用户
        reinit = user_login.goto_Approve_Process(reinit_user)
        process_instance_resp = reinit.open_process_instance(process_name)
        reinit_resp = reinit.approve_submit(param,process_instance_resp)
        # 审批后校验
        verification.after_approve(process_name, reinit_resp, expect, contract_format, DBNodeVerify,
                                   MessageVerify)
        Logger.info("*************** {}结束执行用例 ***************".format(title))

    # 获取yml文件中[驳回后重新审批_不确认路径]的数据参数
    approve_process_params = data['驳回后重新审批_多次审批']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(approve_process_params,"$[*][0]")
    @pytest.mark.parametrize("title, param, expect", approve_process_params,ids=ids_list)
    def test_RollBack_EditCondition_Approve(self, user_login, title, param, expect):
        Logger.info("*************** {}开始执行用例 ***************".format(title))
        allure.dynamic.description(f"{param['description']}")  # 动态解析用例描述在测试报告中展示
        user,process_name = param['user'],param['process_name']
        DBNodeVerify, MessageVerify = '数据库校验', '消息校验'
        contract_format = pact.roll_back_pact_format()  #打回契约格式
        approve_contract_format = pact.approve_pact_format()    # 审批契约格式
        todo_sql = execute_sql.query_node_sql_by(process_name=process_name, all_node=False) # 查询在办步骤节点sql
        main = user_login.goto_Approve_Process(user)    # 登录到审批类实例
        process_instance_resp = main.open_process_instance(process_name)   # 通过流程名称打开流程实例
        back_response = main.approve_submit(param,process_instance_resp)    # 驳回审批
        # 审批后校验
        verification.after_approve(process_name, back_response, expect, contract_format, DBNodeVerify,
                                   MessageVerify)
        # 如果驳回，被驳回步骤只有1人，则直接审批确认路径
        if len(param['action1']) == 1:
            Logger.info("*************** 【{}】再审批确认路径 ***************".format(process_name))
            param.update(action=param['action1'][0])
            DBNodeVerify, MessageVerify, ConfirmPath = '确认路径审批后数据库校验', '确认路径审批后消息校验', '确认路径校验'
            reinit_user = utils.get_column_value_by_two_array(sqlserver_query_return_contain_field(todo_sql), '用户code')[0]  # 查询当前流程在办节点的用户
            main3 = user_login.goto_Approve_Process(reinit_user)    # 登录到审批类实例
            process_instance_resp = main3.open_process_instance(process_name)   # 通过流程名称打开流程实例
            confirm_path_resp = main3.approve_confirm_path(param, process_instance_resp)    # 确认路径
            reinit_resp = main3.approve_submit(param, process_instance_resp)    # 确认路径后提交
            # 审批后校验
            verification.after_approve(process_name, reinit_resp, expect, approve_contract_format, DBNodeVerify,
                                       MessageVerify, confirm_path_resp=confirm_path_resp, confirm_path_verify=ConfirmPath)

        else:
            # 如果驳回，被驳回步骤有多人，则非第一人直接审批，最后一个人执行确认路径
            for i, action in enumerate(param['action1']):
                param.update(action=action)
                # 查询当前流程在办节点的用户
                user2 = utils.get_column_value_by_two_array(sqlserver_query_return_contain_field(todo_sql), '用户code')[0]
                main2 = user_login.goto_Approve_Process(user2)  # 登录到审批类实例
                process_instance_resp = main2.open_process_instance(process_name)   # 通过流程名称打开流程实例
                # 如果是不是最后一个人，则无需确认路径，直接审批
                if i != len(param['action1']) - 1:
                    reinit_resp = main2.approve_submit(param,process_instance_resp) # 审批提交
                    # 审批后校验
                    verification.after_approve(process_name, reinit_resp, expect, approve_contract_format)
                else:
                    # 如果是最后一个人，执行确认路径的代码
                    Logger.info("*************** 【{}】再审批确认路径 ***************".format(process_name))
                    DBNodeVerify, MessageVerify, ConfirmPath = '确认路径审批后数据库校验', '确认路径审批后消息校验', '确认路径校验'
                    confirm_path_resp = main2.approve_confirm_path(param, process_instance_resp)    # 确认路径
                    reinit_resp = main2.approve_submit(param, process_instance_resp)    # 确认路径后提交
                    # 审批后校验
                    verification.after_approve(process_name, reinit_resp, expect, approve_contract_format, DBNodeVerify,
                                               MessageVerify, confirm_path_resp=confirm_path_resp, confirm_path_verify=ConfirmPath)

        Logger.info("*************** {}结束执行用例 ***************".format(title))
